// 
// XmppProtocolFactory.cs
// 
// Copyright © 2007 Philippe Durand <draekz@gmail.com>
// Copyright © 2009 Jiří Zárevúcky <zarevucky.jiri@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//


using System;
using System.Collections.Generic;

using Gdk;
using Gtk;

using Galaxium.Core;
using Galaxium.Protocol;
using Galaxium.Protocol.Gui;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

using Anculus.Core;

using Galaxium.Protocol.Xmpp.Library;

namespace Galaxium.Protocol.Xmpp.GtkGui
{
	public class XmppProtocolFactory: AbstractProtocolFactory, IProtocolGuiFactory<Widget>
	{
		public XmppProtocolFactory ()
			:base (XmppProtocol.Instance)
		{
		}
		
		public XmppProtocolFactory (IProtocol protocol)
			:base (protocol)
		{
		}

		public ISessionWidget<Widget> CreateSessionWidget (IControllerWindow<Widget> window,
		                                                   ISession session)
		{
			ThrowUtility.ThrowIfNull ("session", session);
			
			return new XmppSessionWidget (window, session as XmppSession);
		}

		public virtual IAccountWidget<Widget> CreateAccountWidget ()
		{
			return new XmppAccountWidget ();
		}

		public IChatWidget<Widget> CreateChatWidget (IContainerWindow<Widget> window,
		                                             IConversation conversation)
		{
			if (conversation is XmppConversation)
				return new XmppChatWidget (window, conversation as XmppConversation);
			else if (conversation is XmppConference)
				return new XmppConferenceWidget (window, conversation as XmppConference);
			else if (conversation is XmppPrivateConversation)
				return new XmppPrivateConversationWidget (window, conversation as XmppPrivateConversation);
			else
				throw new ArgumentException ("Invalid type", "conversation");
		}
		
		public override ISession CreateSession (IAccount account)
		{
			return new XmppSession (account as XmppAccount);
		}

		public override IAccount LoadAccount (IConfigurationSection config)
		{
			XmppAccount account = new XmppAccount (config.Name);
			
			// General account settings
			account.Password = config.GetString (Configuration.Account.Password.Name, Configuration.Account.Password.Default);
			account.DisplayName = config.GetString (Configuration.Account.DisplayName.Name, account.UniqueIdentifier);
			account.DisplayMessage = config.GetString (Configuration.Account.DisplayMessage.Name, Configuration.Account.DisplayMessage.Default);
		//	account.DisplayImageContext = config.GetString (Configuration.Account.DisplayImage.Name, Configuration.Account.DisplayImage.Default);
			account.Nickname = config.GetString (Configuration.Account.Nickname.Name, Configuration.Account.Nickname.Default);
		//	account.InitialPresence = XmppPresence.Parse (config.GetString (Configuration.Account.InitialPresence.Name, Configuration.Account.InitialPresence.Default)); FIXME
			account.AutoConnect = config.GetBool (Configuration.Account.AutoConnect.Name, Configuration.Account.AutoConnect.Default);
			account.RememberPassword = config.GetBool (Configuration.Account.RememberPassword.Name, Configuration.Account.RememberPassword.Default);
			
			account.ViewByGroup = config.GetBool (Configuration.Account.ViewByGroup.Name, Configuration.Account.ViewByGroup.Default);
			account.DetailLevel = (ContactTreeDetailLevel)config.GetInt (Configuration.Account.DetailLevel.Name, Configuration.Account.DetailLevel.Default);
			account.SortAlphabetic = config.GetBool (Configuration.Account.SortAlphabetic.Name, Configuration.Account.SortAlphabetic.Default);
			account.SortAscending = config.GetBool (Configuration.Account.SortAscending.Name, Configuration.Account.SortAscending.Default);
			account.ShowOfflineContacts = config.GetBool (Configuration.Account.ShowOfflineContacts.Name, Configuration.Account.ShowOfflineContacts.Default);
			account.ShowEmptyGroups = config.GetBool (Configuration.Account.ShowEmptyGroups.Name, Configuration.Account.ShowEmptyGroups.Default);
			account.ShowSearchBar = config.GetBool (Configuration.Account.ShowSearchBar.Name, Configuration.Account.ShowSearchBar.Default);
			account.GroupOfflineContacts = config.GetBool (Configuration.Account.GroupOfflineContacts.Name, Configuration.Account.GroupOfflineContacts.Default);
			account.ShowDisplayImages = config.GetBool (Configuration.Account.ShowContactImages.Name, Configuration.Account.ShowContactImages.Default);
			account.ShowDisplayNames = config.GetBool (Configuration.Account.ShowContactNames.Name, Configuration.Account.ShowContactNames.Default);
			account.ShowPersonalMessages = config.GetBool (Configuration.Account.ShowContactMessages.Name, Configuration.Account.ShowContactMessages.Default);
			account.ShowNicknames = config.GetBool (Configuration.Account.ShowContactNicknames.Name, Configuration.Account.ShowContactNicknames.Default);
			account.UseDefaultListView = config.GetBool (Configuration.Account.UseDefaultListView.Name, Configuration.Account.UseDefaultListView.Default);
			
			// Xmpp specific settings
			var jid = config.GetString ("JabberID", null);
			account.Jid = jid == null ? null : new JabberID (jid);
			account.ConnectServer = config.GetString ("ConnectServer", "");
			account.ConnectPort = config.GetInt ("ConnectPort", 5222);
			account.AutoPriority = config.GetBool ("AutoPriority", true);
			account.Priority = config.Get<sbyte> ("Priority");
			
			return account;
		}
		
		public override void SaveAccount (IConfigurationSection config, IAccount acc)
		{
			XmppAccount account = acc as XmppAccount;
			
			// General account settings
			config.SetString ("Account", account.UniqueIdentifier);
			config.SetString (Configuration.Account.Password.Name, account.RememberPassword ? account.Password : String.Empty);
		//	config.SetString (Configuration.Account.InitialPresence.Name, XmppPresence.GetCode (account.InitialPresence));
			config.SetString (Configuration.Account.DisplayName.Name, account.DisplayName);
			config.SetString (Configuration.Account.DisplayMessage.Name, account.DisplayMessage);
		//	config.SetString (Configuration.Account.DisplayImage.Name, account.DisplayImageContext);
			config.SetString (Configuration.Account.Nickname.Name, account.Nickname);
			config.SetBool (Configuration.Account.AutoConnect.Name, account.AutoConnect);
			config.SetBool (Configuration.Account.RememberPassword.Name, account.RememberPassword);
			
			config.SetBool (Configuration.Account.ViewByGroup.Name, account.ViewByGroup);
			config.SetInt (Configuration.Account.DetailLevel.Name, (int)account.DetailLevel);
			config.SetBool (Configuration.Account.SortAlphabetic.Name, account.SortAlphabetic);
			config.SetBool (Configuration.Account.SortAscending.Name, account.SortAscending);
			config.SetBool (Configuration.Account.ShowOfflineContacts.Name, account.ShowOfflineContacts);
			config.SetBool (Configuration.Account.ShowEmptyGroups.Name, account.ShowEmptyGroups);
			config.SetBool (Configuration.Account.ShowSearchBar.Name, account.ShowSearchBar);
			config.SetBool (Configuration.Account.GroupOfflineContacts.Name, account.GroupOfflineContacts);
			config.SetBool (Configuration.Account.ShowContactImages.Name, account.ShowDisplayImages);
			config.SetBool (Configuration.Account.ShowContactNames.Name, account.ShowDisplayNames);
			config.SetBool (Configuration.Account.ShowContactMessages.Name, account.ShowPersonalMessages);
			config.SetBool (Configuration.Account.ShowContactNicknames.Name, account.ShowNicknames);
			config.SetBool (Configuration.Account.UseDefaultListView.Name, account.UseDefaultListView);
			
			// Xmpp specific settings
			config.SetString ("JabberID", account.Jid);
			config.SetString ("ConnectServer", account.ConnectServer);
			config.SetInt ("ConnectPort", account.ConnectPort);
			config.SetBool ("AutoPriority", account.AutoPriority);
			config.SetInt ("Priority", account.Priority);
		}
		
		public override IAccountCache CreateAccountCache (IAccount account, string directory)
		{
			return new XmppAccountCache (account, directory);
		}

		public override IMessageSplitter CreateSplitter ()
		{
			return null;
		//	return new XmppSplitter ();
		}
		
		public static Pixbuf StatusLookup (IPresence item, IIconSize size)
		{
			if (object.ReferenceEquals (item, XmppPresence.Chat))
				return IconUtility.GetIcon ("galaxium-status-chat", size);
			
			if (object.ReferenceEquals (item, XmppPresence.Error))
				return IconUtility.GetIcon ("galaxium-status-error", size);
			
			return IconUtility.StatusLookup (item, size);
		}
	}
}